package com.Hermes.User;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;

import javax.crypto.IllegalBlockSizeException;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.System.arraycopy;
import static java.lang.System.out;


public class DX {


    private final PRF_PRP_Hash pph;
    private final ConcurrentHashMap<BigInteger, byte[]> dx;
    private final SecureRandom rng;
    private final ConcurrentHashMap<Long, Long> ii2i;
    private BigInteger kv;

    public DX(PRF_PRP_Hash pph, ConcurrentHashMap<Long, Long> ii2i) {
        this.pph = pph;
        this.ii2i = ii2i;
        rng = new SecureRandom();
        dx = new ConcurrentHashMap<>();

    }

    public ConcurrentHashMap<BigInteger, byte[]> getDx() {
        return dx;
    }

    public BigInteger getKv() {
        return kv;
    }

    /*
     * 参数：对应数组的下标，临时密钥的长度，点对象
     * */
    public void add(node n1) throws IllegalBlockSizeException {//生成256位的暂时密钥
        byte[] f4 = new byte[32];

        do {
            n1.kv = new BigInteger(256, rng);
        } while (n1.kv.toByteArray().length != 32);
        do {
            n1.rv = new BigInteger(256, rng);
        } while (n1.rv.toByteArray().length != 32);


        pph.use_F4(BigInteger.valueOf(ii2i.get(n1.id)).toByteArray(), f4);

        byte[] tsecondB = new byte[32];

        byte[] btmp = ByteTools.XOR(n1.kv.toByteArray(), f4);
        if (n1.index == 45) {
            out.println("btmp");
            out.println("new BigInteger(btmp) = " + new BigInteger(btmp));
        }
        arraycopy(btmp, 0, tsecondB, 0, btmp.length);

        byte[] secondB = ByteTools.merge(BigInteger.valueOf(n1.index).toByteArray(), tsecondB);
        byte[] k = new BigDecimal(ii2i.get(n1.id)).toBigInteger().toByteArray(), k1 = new byte[k.length];


        pph.use_T2(k, k1);
        BigInteger bk1 = new BigInteger(k1);

        dx.put(bk1, secondB);

    }

    protected int get_addr(node n1) throws IllegalBlockSizeException {
        byte[] msg = new byte[32];
        String ts = String.valueOf(n1.id);
        pph.use_F4(ts.getBytes(), msg);

        byte[] k = new BigDecimal(ii2i.get(n1.id)).toBigInteger().toByteArray(), k1 = new byte[k.length];

        pph.use_T2(k, k1);
        BigInteger bk1 = new BigInteger(k1);
        byte[] sv = dx.get(bk1);


        byte[] ind = new byte[sv.length - 32];
        arraycopy(sv, 0, ind, 0, sv.length - 32);
        return new BigInteger(ind).intValue();

    }


    public int getIndex(String T2v, String F4v) {
        byte[] bF4v = new BigInteger(F4v).toByteArray();
        byte[] b1 = dx.get(new BigInteger(T2v));
        out.println("new BigInteger(b1) = " + new BigInteger(b1));
        byte[] secondB = new byte[32];
        byte[] firstB = new byte[b1.length - 32];
        for (int i = b1.length - 32, j = 0; i < b1.length; i++) {
            secondB[j] = b1[i];
            ++j;
        }
        arraycopy(b1, 0, firstB, 0, b1.length - 32);

        out.println("new BigInteger(secondB) = " + new BigInteger(secondB));

        this.kv = new BigInteger(ByteTools.XOR(secondB, bF4v));


        out.println("kv.toByteArray()");
        ByteTools._DEBUGBYTES(kv.toByteArray());
        return new BigInteger(firstB).intValue();
    }
    @SneakyThrows
    public void writeDX(String fileName)  {
        ObjectMapper mapper=new ObjectMapper();
        String s = mapper.writeValueAsString(dx);
        mapper.writeValue(new File(fileName),s);
    }
}
